﻿using FFmpeg.AutoGen;
using FFmpegWinui3.UlitFolder;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.UI.Xaml;

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Documents;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using System.Threading.Tasks;
using Windows.Graphics.DirectX;

// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.

namespace FFmpegWinui3.MediaFolder
{
    public unsafe partial class MediaElement : Control
    {

        CanvasControl canvas;
        CanvasBitmap bitmap;
        private object SyncLock = new object();

        MediaContainer mc = new MediaContainer();


        const int BUFFER_DURATION = 5000;
        //NAudio音频播放组件
        private WaveOut waveOut;
        private BufferedWaveProvider bufferedWaveProvider;
        TimeSpan audioMaxBufferedDuration;

        public MediaElement()
        {
            this.DefaultStyleKey = typeof(MediaElement);
        }

        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            canvas = GetTemplateChild("canvas") as CanvasControl;
            if (canvas != null)
            {
                canvas.Draw += (s, e) =>
                {
                    if (bitmap == null)
                        return;

                    var te = Win2DUlit.CalcutateImageCenteredTransform(canvas.ActualSize, bitmap.Size);
                    te.Source = bitmap;
                    e.DrawingSession.DrawImage(te);
                };
                waveOut = new WaveOut();
                bufferedWaveProvider = new BufferedWaveProvider(new WaveFormat());
                waveOut.Init(bufferedWaveProvider);
                waveOut.Play();
                audioMaxBufferedDuration = TimeSpan.FromMilliseconds(BUFFER_DURATION);
                CancellationTokenSource cts = new CancellationTokenSource();
                Task PlayTask = new Task(() =>
                 {
                     ProcessPlay();
                 }, cts.Token);
                PlayTask.Start();
            }
        }

        private void ProcessPlay()
        {
            while (true)
            {
                if (Playing)
                {
                    lock (SyncLock)
                    {
                        Position = mc.Position;
                        mc.ReadNextPacket();
                        if (mc.Video != null)
                        {
                            var videoBytes = mc.GetVideoFrameData();
                            if (videoBytes != null)
                            {
                                bitmap = CanvasBitmap.CreateFromBytes(CanvasDevice.GetSharedDevice(), videoBytes, mc.Video.FrameWidth, mc.Video.FrameHeight, DirectXPixelFormat.B8G8R8A8UIntNormalized);
                                canvas.Invalidate();
                            }
                            var audioBytes = mc.GetAudioFrameData();
                            if (audioBytes != null)
                            {
                                if (bufferedWaveProvider.BufferLength <= bufferedWaveProvider.BufferedBytes)
                                {
                                    bufferedWaveProvider.ClearBuffer();
                                }
                                bufferedWaveProvider.AddSamples(audioBytes, 0, audioBytes.Length);//向缓存中添加音频样本
                            }
                        }
                    }

                }
            }
        }
    }

    public unsafe partial class MediaElement
    {
        #region Playing     
        /// <summary>
        /// 获取或设置Playing的值
        /// </summary>  
        public bool Playing { get; protected set; }

        #endregion




        #region Source     
        /// <summary>
        /// 获取或设置Source的值
        /// </summary>  
        public string Source
        {
            get { return (string)GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }

        /// <summary>
        /// 标识 Source 依赖属性。
        /// </summary>
        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register("Source", typeof(string), typeof(MediaElement), new PropertyMetadata(null, OnSourceChanged));

        private static void OnSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            MediaElement target = obj as MediaElement;
            string oldValue = (string)args.OldValue;
            string newValue = (string)args.NewValue;
            if (oldValue != newValue)
                target.OnSourceChanged(oldValue, newValue);
        }

        protected virtual void OnSourceChanged(string oldValue, string newValue)
        {
            if (oldValue != newValue)
            {
                //mc.InitMedia((string)newValue);
                HasVideo = false;
                if (mc.Video != null)
                {
                    HasVideo = true;
                    VideoCodecName = mc.Video.CodecName;
                    VideoBitrate = mc.Video.Bitrate;
                    VideoWidth = mc.Video.FrameWidth;
                    VideoHeight = mc.Video.FrameHeight;
                    VideoFrameRate = mc.Video.FrameRate;
                }
                HasAudio = false;

                if (mc.Audio != null)
                {
                    AudioCodecName = mc.Audio.CodecName;
                    AudioBirate = mc.Audio.Bitrate;
                    AudioChannels = mc.Audio.Channels;
                    AudioSampleRate = mc.Audio.SampleRate;
                    AudioBitsPerSample = mc.Audio.BitsPerSample;
                }

            }

        }
        #endregion



        #region Duration     
        /// <summary>
        /// 获取或设置Duration的值
        /// </summary>  
        public TimeSpan Duration
        {
            get { return (TimeSpan)GetValue(DurationProperty); }
            protected set { SetValue(DurationProperty, value); }
        }

        /// <summary>
        /// 标识 Duration 依赖属性。
        /// </summary>
        public static readonly DependencyProperty DurationProperty =
            DependencyProperty.Register("Duration", typeof(TimeSpan), typeof(MediaElement), new PropertyMetadata(TimeSpan.FromSeconds(0)));
        #endregion


        #region HasVideo     
        /// <summary>
        /// 获取或设置HasVideo的值
        /// </summary>  
        public bool HasVideo
        {
            get { return (bool)GetValue(HasVideoProperty); }
            protected set { SetValue(HasVideoProperty, value); }
        }

        /// <summary>
        /// 标识 HasVideo 依赖属性。
        /// </summary>
        public static readonly DependencyProperty HasVideoProperty =
            DependencyProperty.Register("HasVideo", typeof(bool), typeof(MediaElement), new PropertyMetadata(false));
        #endregion


        #region HasAudio     
        /// <summary>
        /// 获取或设置HasAudio的值
        /// </summary>  
        public bool HasAudio
        {
            get { return (bool)GetValue(HasAudioProperty); }
            protected set { SetValue(HasAudioProperty, value); }
        }

        /// <summary>
        /// 标识 HasAudio 依赖属性。
        /// </summary>
        public static readonly DependencyProperty HasAudioProperty =
            DependencyProperty.Register("HasAudio", typeof(bool), typeof(MediaElement), new PropertyMetadata(false));
        #endregion


        #region VideoCodecName     
        /// <summary>
        /// 获取或设置VideoCodecName的值
        /// </summary>  
        public string VideoCodecName
        {
            get { return (string)GetValue(VideoCodecNameProperty); }
            protected set { SetValue(VideoCodecNameProperty, value); }
        }

        /// <summary>
        /// 标识 VideoCodecName 依赖属性。
        /// </summary>
        public static readonly DependencyProperty VideoCodecNameProperty =
            DependencyProperty.Register("VideoCodecName", typeof(string), typeof(MediaElement), new PropertyMetadata(null));
        #endregion


        #region VideoBitrate     
        /// <summary>
        /// 获取或设置VideoBitrate的值
        /// </summary>  
        public int VideoBitrate
        {
            get { return (int)GetValue(VideoBitrateProperty); }
            protected set { SetValue(VideoBitrateProperty, value); }
        }

        /// <summary>
        /// 标识 VideoBitrate 依赖属性。
        /// </summary>
        public static readonly DependencyProperty VideoBitrateProperty =
            DependencyProperty.Register("VideoBitrate", typeof(int), typeof(MediaElement), new PropertyMetadata(0));
        #endregion

        #region VideoWidth     
        /// <summary>
        /// 获取或设置VideoWidth的值
        /// </summary>  
        public int VideoWidth
        {
            get { return (int)GetValue(VideoWidthProperty); }
            protected set { SetValue(VideoWidthProperty, value); }
        }

        /// <summary>
        /// 标识 VideoWidth 依赖属性。
        /// </summary>
        public static readonly DependencyProperty VideoWidthProperty =
            DependencyProperty.Register("VideoWidth", typeof(int), typeof(MediaElement), new PropertyMetadata(0));
        #endregion

        #region VideoHeight     
        /// <summary>
        /// 获取或设置VideoHeight的值
        /// </summary>  
        public int VideoHeight
        {
            get { return (int)GetValue(VideoHeightProperty); }
            set { SetValue(VideoHeightProperty, value); }
        }

        /// <summary>
        /// 标识 VideoHeight 依赖属性。
        /// </summary>
        public static readonly DependencyProperty VideoHeightProperty =
            DependencyProperty.Register("VideoHeight", typeof(int), typeof(MediaElement), new PropertyMetadata(0));
        #endregion


        #region VideoFrameRate     
        /// <summary>
        /// 获取或设置VideoFrameRate的值
        /// </summary>  
        public double VideoFrameRate
        {
            get { return (double)GetValue(VideoFrameRateProperty); }
            protected set { SetValue(VideoFrameRateProperty, value); }
        }

        /// <summary>
        /// 标识 VideoFrameRate 依赖属性。
        /// </summary>
        public static readonly DependencyProperty VideoFrameRateProperty =
            DependencyProperty.Register("VideoFrameRate", typeof(double), typeof(MediaElement), new PropertyMetadata(0d));
        #endregion


        #region AudioCodecName     
        /// <summary>
        /// 获取或设置AudioCodecName的值
        /// </summary>  
        public string AudioCodecName
        {
            get { return (string)GetValue(AudioCodecNameProperty); }
            protected set { SetValue(AudioCodecNameProperty, value); }
        }

        /// <summary>
        /// 标识 AudioCodecName 依赖属性。
        /// </summary>
        public static readonly DependencyProperty AudioCodecNameProperty =
            DependencyProperty.Register("AudioCodecName", typeof(string), typeof(MediaElement), new PropertyMetadata(""));
        #endregion


        #region AudioBirate     
        /// <summary>
        /// 获取或设置AudioBirate的值
        /// </summary>  
        public int AudioBirate
        {
            get { return (int)GetValue(AudioBirateProperty); }
            protected set { SetValue(AudioBirateProperty, value); }
        }

        /// <summary>
        /// 标识 AudioBirate 依赖属性。
        /// </summary>
        public static readonly DependencyProperty AudioBirateProperty =
            DependencyProperty.Register("AudioBirate", typeof(int), typeof(MediaElement), new PropertyMetadata(0));


        #endregion


        #region AudioChannels     
        /// <summary>
        /// 获取或设置AudioChannels的值
        /// </summary>  
        public int AudioChannels
        {
            get { return (int)GetValue(AudioChannelsProperty); }
            protected set { SetValue(AudioChannelsProperty, value); }
        }

        /// <summary>
        /// 标识 AudioChannels 依赖属性。
        /// </summary>
        public static readonly DependencyProperty AudioChannelsProperty =
            DependencyProperty.Register("AudioChannels", typeof(int), typeof(MediaElement), new PropertyMetadata(0));

        #endregion

        #region AudioSampleRate     
        /// <summary>
        /// 获取或设置AudioSampleRate的值
        /// </summary>  
        public long AudioSampleRate
        {
            get { return (long)GetValue(AudioSampleRateProperty); }
            protected set { SetValue(AudioSampleRateProperty, value); }
        }

        /// <summary>
        /// 标识 AudioSampleRate 依赖属性。
        /// </summary>
        public static readonly DependencyProperty AudioSampleRateProperty =
            DependencyProperty.Register("AudioSampleRate", typeof(long), typeof(MediaElement), new PropertyMetadata(0));


        #endregion

        #region AudioBitsPerSample     
        /// <summary>
        /// 获取或设置AudioBitsPerSample的值
        /// </summary>  
        public long AudioBitsPerSample
        {
            get { return (long)GetValue(AudioBitsPerSampleProperty); }
            protected set { SetValue(AudioBitsPerSampleProperty, value); }
        }

        /// <summary>
        /// 标识 AudioBitsPerSample 依赖属性。
        /// </summary>
        public static readonly DependencyProperty AudioBitsPerSampleProperty =
            DependencyProperty.Register("AudioBitsPerSample", typeof(long), typeof(MediaElement), new PropertyMetadata(0));
        #endregion

        #region Position     
        /// <summary>
        /// 获取或设置Position的值
        /// </summary>  
        public TimeSpan Position { get; private set; }
        //{
        //    get { return (TimeSpan)GetValue(PositionProperty); }
        //    protected set { SetValue(PositionProperty, value); }
        //}

        ///// <summary>
        ///// 标识 Position 依赖属性。
        ///// </summary>
        //public static readonly DependencyProperty PositionProperty =
        //    DependencyProperty.Register("Position", typeof(TimeSpan), typeof(MediaElement), new PropertyMetadata(TimeSpan.FromSeconds(0), OnPositionChanged));

        //private static void OnPositionChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        //{
        //    MediaElement target = obj as MediaElement;
        //    TimeSpan oldValue = (TimeSpan)args.OldValue;
        //    TimeSpan newValue = (TimeSpan)args.NewValue;
        //    if (oldValue != newValue)
        //        target.OnPositionChanged(oldValue, newValue);
        //}

        //protected virtual void OnPositionChanged(TimeSpan oldValue, TimeSpan newValue)
        //{
        //}
        #endregion

    }



    public unsafe partial class MediaElement
    {




    }

    public unsafe partial class MediaElement
    {
        public void Seek(int seekTime)
        {




        }

        public void Play()
        {
            lock (SyncLock)
            {
                if (Playing) return;
                Playing = true;
                mc.Play();
            }
        }
        public void Pause()
        {
            lock (SyncLock)
            {
                if (!Playing) return;
                Playing = false;
                mc.Pause();
            }
        }
        public void Stop()
        {
            lock (SyncLock)
            {
                if (!Playing) return;
                Playing = false;
                mc.Stop();
                Position = TimeSpan.FromSeconds(0);
            }
        }

        public void SetSource(string url)
        {
            mc.InitMedia(url);
            Play();
        }
    }
}
